﻿using System;
using System.Data;
using ErickOrlando.Utilidades;

namespace ErickOrlando.Utilidades.Data
{

    /// <summary>
    /// Obtiene un valor de un <see cref="IDataReader"/> en base al nombre del Campo
    /// </summary>
    public static class DataReader
    {

        private const int indice = -1;

        /// <summary>
        /// Obtiene un valor de Cadena
        /// </summary>
        public static String GetString(this IDataReader dr, string nombre)
        {
            int drGetOrdinal = dr.GetOrdinal(nombre);
            if (drGetOrdinal > indice)
                return dr.IsDBNull(drGetOrdinal) ? String.Empty : dr.GetString(drGetOrdinal);
            throw new ArgumentException(String.Format(Properties.Resources.msgNoHayColumna, nombre));
        }

        /// <summary>
        /// Obtiene un valor de un entero de 16 bits
        /// </summary>
        public static Int16 GetInt16(this IDataReader dr, string nombre)
        {
            int drGetOrdinal = dr.GetOrdinal(nombre);
            if (drGetOrdinal > indice)
                return dr.IsDBNull(drGetOrdinal) ? (short)0 : dr.GetInt16(drGetOrdinal);
            throw new ArgumentException(String.Format(Properties.Resources.msgNoHayColumna, nombre));
        }

        /// <summary>
        /// Obtiene un valor de un entero de 32 bits
        /// </summary>
        public static Int32 GetInt32(this IDataReader dr, string nombre)
        {
            int drGetOrdinal = dr.GetOrdinal(nombre);
            if (drGetOrdinal > indice)
                return dr.IsDBNull(drGetOrdinal) ? 0 : dr.GetInt32(drGetOrdinal);
            throw new ArgumentException(String.Format(Properties.Resources.msgNoHayColumna, nombre));
        }

        /// <summary>
        /// Obtiene un valor de un entero de 64 bits
        /// </summary>
        public static Int64 GetInt64(this IDataReader dr, string nombre)
        {
            int drGetOrdinal = dr.GetOrdinal(nombre);
            if (drGetOrdinal > indice)
                return dr.IsDBNull(drGetOrdinal) ? (long)0 : dr.GetInt64(drGetOrdinal);
            throw new ArgumentException(String.Format(Properties.Resources.msgNoHayColumna, nombre));
        }

        /// <summary>
        /// Obtiene un valor booleano
        /// </summary>
        public static bool GetBoolean(this IDataReader dr, string nombre)
        {
            int drGetOrdinal = dr.GetOrdinal(nombre);
            if (drGetOrdinal > indice)
                return dr.IsDBNull(drGetOrdinal) ? false : dr.GetBoolean(drGetOrdinal);
            throw new ArgumentException(String.Format(Properties.Resources.msgNoHayColumna, nombre));
        }

        /// <summary>
        /// Obtiene un valor Decimal
        /// </summary>
        public static Decimal GetDecimal(this IDataReader dr, string nombre)
        {
            int drGetOrdinal = dr.GetOrdinal(nombre);
            if (drGetOrdinal > indice)
                return dr.IsDBNull(drGetOrdinal) ? (decimal)0 : dr.GetDecimal(drGetOrdinal);
            throw new ArgumentException(String.Format(Properties.Resources.msgNoHayColumna, nombre));
        }

        /// <summary>
        /// Obtiene un valor de Fecha
        /// </summary>
        public static DateTime GetDateTime(this IDataReader dr, string nombre)
        {
            int drGetOrdinal = dr.GetOrdinal(nombre);
            if (drGetOrdinal > indice)
                return dr.IsDBNull(drGetOrdinal) ? DateTime.Now : dr.GetDateTime(drGetOrdinal);
            throw new ArgumentException(String.Format(Properties.Resources.msgNoHayColumna, nombre));
        }

        /// <summary>
        /// Obtiene un valor Double
        /// </summary>
        public static double GetDouble(this IDataReader dr, string nombre)
        {
            int drGetOrdinal = dr.GetOrdinal(nombre);
            if (drGetOrdinal > indice)
                return dr.IsDBNull(drGetOrdinal) ? 0D : dr.GetDouble(drGetOrdinal);
            throw new ArgumentException(String.Format(Properties.Resources.msgNoHayColumna, nombre));
        }

        /// <summary>
        /// Obtiene un valor Byte
        /// </summary>
        public static byte GetByte(this IDataReader dr, string nombre)
        {
            int drGetOrdinal = dr.GetOrdinal(nombre);
            if (drGetOrdinal > indice)
                return dr.IsDBNull(drGetOrdinal) ? (byte)0 : dr.GetByte(drGetOrdinal);
            throw new ArgumentException(String.Format(Properties.Resources.msgNoHayColumna, nombre));
        }

        /// <summary>
        /// Obtiene un valor Char
        /// </summary>
        public static char GetChar(this IDataReader dr, string nombre)
        {
            int drGetOrdinal = dr.GetOrdinal(nombre);
            if (drGetOrdinal > indice)
                return dr.IsDBNull(drGetOrdinal) ? ' ' : dr.GetChar(drGetOrdinal);
            throw new ArgumentException(String.Format(Properties.Resources.msgNoHayColumna, nombre));
        }

        /// <summary>
        /// Obtiene un valor Object
        /// </summary>
        public static object GetValue(this IDataReader dr, string nombre)
        {
            int drGetOrdinal = dr.GetOrdinal(nombre);
            if (drGetOrdinal > indice)
                return dr.IsDBNull(drGetOrdinal) ? null : dr.GetValue(drGetOrdinal);
            throw new ArgumentException(String.Format(Properties.Resources.msgNoHayColumna, nombre));
        }

        /// <summary>
        /// Devuelve una cadena vacía en caso de no encontrar la columna
        /// </summary>
        public static string GetStringEmpty(this IDataReader dr, string campo)
        {
            return dr.ExisteCampo(campo) ? dr.GetString(campo) : string.Empty;
        }

        /// <summary>
        /// Devuelve 0 (Cero) si no existe la columna
        /// </summary>
        public static int GetInt(this IDataReader dr, string campo)
        {
            return dr.ExisteCampo(campo) ? dr.GetInt32(campo) : 0;
        }

        /// <summary>
        /// Devuelve 0 (Cero) en caso de no encontrar el campo Decimal
        /// </summary>
        public static decimal GetDecimalCero(this IDataReader dr, string campo)
        {
            return dr.ExisteCampo(campo) ? dr.GetDecimal(campo) : 0;
        }

        /// <summary>
        /// Devuelve la fecha actual en caso de no encontrar el campo
        /// </summary>
        public static DateTime GetDateTimeNow(this IDataReader dr, string campo)
        {
            return dr.ExisteCampo(campo) ? dr.GetDateTime(campo) : DateTime.Now;
        }

        /// <summary>
        /// Permite saber si existe un campo en el IDataReader
        /// </summary>
        /// <param name="dr">IDataReader que se usará</param>
        /// <param name="nombre">Nombre del Campo</param>
        /// <returns>bool</returns>
        public static bool ExisteCampo(this IDataReader dr, string nombre)
        {
            foreach (DataRow columna in dr.GetSchemaTable().Rows)
                if (columna.ItemArray[0].ToString().Equals(nombre, StringComparison.CurrentCultureIgnoreCase))
                    return true;
            return false;
        }

    }
}
